﻿using Coolzon.Common;
using Coolzon.UI.Common;
using Coolzon.UI.Core;
using Coolzon.UI.Core.Animation;
using Coolzon.UI.Core.Parts;
using Coolzon.UI.Core.Runtime;
using Coolzon.UI.Core.Views;
using CPPEI.Coolzon.UI.Data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using RT = Coolzon.Metadata.Runtime;

namespace Coolzon.UI.ViewerApp.Views
{
    /// <summary>
    /// Interaction logic for RenderView.xaml
    /// 用于显示的主视图
    /// </summary>
    public partial class RenderView : View, IFrameContainer
    {
        public RT.Solution Solution { get; private set; }
        public RT.Scene CurrentScene { get; private set; }
        public RT.Area CurrentArea { get; private set; }

        /// <summary>
        /// 弹出视图
        /// </summary>
        private List<PopView> _popViews;

        /// <summary>
        /// 是否在加载时创建新的组件实例，当弹出一个新的场景时，我们需要创建一个新的场景对象防止一个场景加载到多个renderview中
        /// 到后期应该考虑，一个renderview打包一组场景实例
        /// </summary>
        private bool _isLoadPartFromCache = true;

        /// <summary>
        /// 当前被定位到的区域索引
        /// </summary>
        private int _currentLocatedAreaIndex = 0;
        public Coolzon.UI.Core.Frame Frame
        {
            get
            {
                return _ctlMainFrame;
            }
        }

        public RenderView()
        {
            InitializeComponent();

            _ctlMainFrame.OnSceneUpdated += _ctlMainFrame_OnSceneUpdated;
            _ctlMainFrame.OnSceneOpened += _ctlMainFrame_OnSceneOpened;

            // 初始化viewstate
            _viewState = ViewState.FromToken(string.Empty);
            ctlRadioFill.IsChecked = true;
        }

        public RenderView(RT.Solution solution)
            : this()
        {
            Solution = solution;

            _popViews = new List<PopView>();

            _ctlMainFrame.Init(Solution);

            if (Solution != null && _viewState != null)
            {
                _viewState.SolutionName = Solution.Name;
            }
        }

        /// <summary>
        /// 子renderview中显示的组件，每次都重新创建
        /// </summary>
        /// <param name="parentView"></param>
        public RenderView(RenderView parentView)
            : this(parentView.Solution)
        {
            _isLoadPartFromCache = true;

            _ctlMainFrame.SetAutoSize();
        }

        protected override void OnActive()
        {
            FocusManager.SetFocusedElement(this, textbox);
            if (IsFirstActive)
            {
                // 打开第一个场景
                OpenScene(SwitchMode.Replace, "", "Scene", Solution.Scenes.First().Name, new OpenSceneArgs());
            }
        }

        protected override void OnClose()
        {
            //_ctlMainFrame.Clear();
        }

        /// <summary>
        /// 切换到场景
        /// </summary>
        /// <param name="sceneName"></param>
        /// <param name="args"></param>
        public bool SwitchToScene(string sceneName, OpenSceneArgs args)
        {
            if (CurrentScene != null && CurrentScene.Name == sceneName)
            {
                //if (args != null && args.GetBool("sys:isresetviewstate"))
                //{
                //    // 还原到初始状态
                //    (_ctlMainFrame.CurrentPart as Scene).Reset();
                //    //// 发送更新事件
                //    //Common.EventBus.Instance.Publish(new SceneUpdateEvent(_ctlMainFrame.CurrentPart as ScenePart, SceneUpdateReason.ResetScene));
                //}
                return true;
            }

            RT.Scene bingoSceneMetadata = RT.SolutionUtil.GetScene(Solution, sceneName);

            if (bingoSceneMetadata != null)
            {
                if (_ctlMainFrame.PartContext != null)
                {
                    _ctlMainFrame.PartContext.IsShowActiveXPart = UIContext.Current.IsShowActiveXPart;
                }

                CurrentScene = bingoSceneMetadata;
                System.Collections.Hashtable componentTable = new System.Collections.Hashtable();

                Scene scene = PartInstanceCache.GetSceneInstance("scene", bingoSceneMetadata, componentTable);
                //scene.Create(_ctlMainFrame.PartContext);
                //if (args != null)
                //{
                //    foreach (string key in args.ParametersString.Keys)
                //    {
                //        Debug.WriteLine(string.Format("注入属性Name:{0}\tValue:{1}到场景:{2}", key, args.ParametersString[key], scene.Name));
                //        scene.Parameters.Set(key, args.ParametersString[key]);
                //    }
                //}

                if (scene != null)
                {
                    if (_ctlMainFrame.ComponentTable!=null)
                    {
                        _ctlMainFrame.ComponentTable.Clear();
                        _ctlMainFrame.ComponentTable = null;
                    }
                    _ctlMainFrame.ComponentTable = componentTable;
                    _ctlMainFrame.ShowScene(Solution, scene, SwitchAnimationFactory.Create("FADE"));
                }

                //_ctlMainFrame.Active(bingoSceneMetadata, UIContext.Current.IsShowActiveXPart, args);
                return true;
            }
            else
            {
                return false;
            }
        }

        ///// <summary>
        ///// 切换显示一个区域
        ///// </summary>
        ///// <param name="sceneName"></param>
        ///// <param name="areaName"></param>
        //public void SwitchToArea(string sceneName, string areaName)
        //{
        //    if (CurrentArea != null && CurrentArea.Name == areaName)
        //    {
        //        return;
        //    }

        //    RT.Scene bingoSceneMetadata = RT.SolutionUtil.GetScene(Solution, sceneName);
        //    RT.Area bingoAreaMetadata = RT.SolutionUtil.GetArea(Solution, sceneName, areaName);
        //    if (bingoAreaMetadata != null)
        //    {
        //        CurrentScene = bingoSceneMetadata;
        //        CurrentArea = bingoAreaMetadata;
        //        Part areaPart = PartInstanceCache.GetAreaInstance(bingoSceneMetadata, bingoAreaMetadata);

        //        if (areaPart != null)
        //        {
        //            //_ctlMainFrame.ShowScene(areaPart, SwitchAnimationFactory.Create("FADE"));
        //        }
        //        _ctlMainFrame.Active(null);
        //    }
        //}

        /// <summary>
        /// 滚动到区域
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="area"></param>
        //public void ScrollToArea(RT.Scene sceneMetadata, RT.Area areaMetadata)
        //{
        //    if (CurrentScene == null || CurrentScene.Name != sceneMetadata.Name)
        //    {
        //        return;
        //    }

        //    if (sceneMetadata != null)
        //    {
        //        CurrentScene = sceneMetadata;
        //        Scene scenePart = PartInstanceCache.GetSceneInstance("scene", sceneMetadata, _isLoadPartFromCache) as Scene;

        //        if (scenePart != null)
        //        {
        //            Area areaPart = scenePart.GetChildPart(areaMetadata.Name, false) as Area;
        //            if (areaPart != null)
        //            {
        //                scenePart.ResetHorizontalLoop();
        //                _ctlMainFrame.ScrollToPart(areaPart);
        //            }
        //        }
        //        //_ctlMainFrame.Active();
        //    }
        //}

        /// <summary>
        /// 滚动到一个具体的位置
        /// </summary>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        public void ScrollToPos(double offsetX, double offsetY)
        {
            //_ctlMainFrame.MoveCameraToPos(offsetX, offsetY);
        }

        private void _ctlCheckOriginal_Checked(object sender, RoutedEventArgs e)
        {
            //if (sender == _ctlCheckOriginal)
            //{
            //    _ctlMainFrame.Stretch = DisplayMode.Original;
            //}
            //else if (sender == _ctlCheckHStretch)
            //{
            //    _ctlMainFrame.Stretch = DisplayMode.HStretch;
            //}
            //else if (sender == _ctlCheckVStretch)
            //{
            //    _ctlMainFrame.Stretch = DisplayMode.VStretch;
            //}
            //else
            //{
            //    _ctlMainFrame.Stretch = DisplayMode.Stretch;
            //}
            //_ctlMainFrame.UpdateDisplayMode();

            //if (_ctlMainFrame.FrameSize != null && _ctlMainFrame.ContentSize != null)
            //{
            //    _ctlTextSize.Text = string.Format("{0}-{1}/{2}-{3}", _ctlMainFrame.FrameSize.Width,
            //        _ctlMainFrame.FrameSize.Height,
            //        _ctlMainFrame.ContentSize.Width,
            //        _ctlMainFrame.ContentSize.Height);
            //}
        }

        #region open/pop scene

        /// <summary>
        /// 切换场景
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="frameName"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="data"></param>
        public void OpenScene(SwitchMode mode, string frameName, string type, string name, OpenSceneArgs args)
        {
            Logger.DebugToTag("Coolon.UI", string.Format("打开场景:\"{0}\",mode:\"{1}\"",
                name,
                mode));

            if (mode == SwitchMode.Replace)
            {
                OnOpenScene(frameName, type, name, args);
            }
            else
            {
                OnPopScene(frameName, type, name, args);
            }
        }

        /// <summary>
        /// 打开场景
        /// </summary>
        /// <param name="frameName"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="args"></param>
        private void OnOpenScene(string frameName, string type, string name, OpenSceneArgs args)
        {
            this.Dispatcher.Invoke(() =>
            {
                #region 关闭弹出层
                for (int index = 0; index < _popViews.Count; index++)
                {
                    _popViews[index].Submit();
                    PopView popView = _popViews[index] as PopView;
                    Scene scene = (popView.ContentView as RenderView).GetCurrentPart() as Scene;
                    if (scene != null)
                    {
                        Logger.DebugToTag("UI", string.Format("销毁-位置2,PopView，Name:{0}", scene.XFullName));
                        scene.Destroy();
                    }
                    else
                    {
                        Logger.ErrorToTag("UI", string.Format("存在弹出层，弹出层里没有场景，弹出视图里的contentView：{0}", popView.ContentView));
                    }
                    Logger.DebugToTag("UI", string.Format("ClearAllParts -OnBack, sceneName:{0}", popView.GetSceneName()));
                    (popView.ContentView as RenderView).ClearAllParts();
                }
                _popViews.Clear();
                #endregion

                try
                {

                    if (SwitchToScene(name, args))
                    {
                        // 更新viewState
                        this._viewState.OpenScene(name, OpenSceneArgs.GetParametersString(args));
                        this._viewState.Update();

                        //Coolzon.Event.Core.CoreOpenSceneCompletedEvent @event = new Coolzon.Event.Core.CoreOpenSceneCompletedEvent(SwitchMode.Replace, frameName, name, args);
                        //Coolzon.Event.Core.CoreEventBus.Publish(@event);
                    }
                }
                catch(Exception ex)
                {
                    Logger.ErrorToTag("Coolzon.UI", string.Format("RenderView.OnOpenScene发生错误,scene：{0}, ex:{1}", name, ex));
                }
            });
        }

        private void OnPopScene(string frameName, string type, string name, OpenSceneArgs args)
        {
            this.Dispatcher.Invoke(new Action(() =>
            {
                RT.Scene scene = RT.SolutionUtil.GetScene(Solution, name);
                if (scene != null)
                {
                    //检查是否在弹出的场景里已经有这个场景了
                    for (int index = 0; index < this._popViews.Count; index++)
                    {
                        if (string.Equals((this._popViews[index].ContentView as RenderView).CurrentScene.Name, scene.Name))
                        {
                            Logger.DebugToTag("RenderView", string.Format("pop scene:{0}失败，因为场景已经在弹出列表中", scene.Name));
                            return;
                        }
                    }

                    RenderView contentView = new RenderView(this);
                    //contentView.Width = scene.;
                    //contentView.Height = 400;
                    contentView.Tag = scene;
                    PopView popView = new PopView(contentView);
                    this._ctlLayout.Children.Add(popView);
                    contentView.GetPartContext().IsRoot = false;
                    contentView.SwitchToScene(name, args);

                    if (contentView.GetCurrentPart() != null)
                    {
                    }

                    if (_ctlMainFrame.CurrentPart != null)
                    {
                        // 冻结当前的场景
                       // _ctlMainFrame.CurrentPart.Frozen();
                    }

                    popView.Close += popView_Close;
                    _popViews.Add(popView);

                    // 更新viewState
                    this._viewState.PopScene(name, OpenSceneArgs.GetParametersString(args));
                    this._viewState.Update();

                    //Coolzon.Event.Core.CoreOpenSceneCompletedEvent @event = new Coolzon.Event.Core.CoreOpenSceneCompletedEvent(SwitchMode.Pop, frameName, name, args);
                    //Coolzon.Event.Core.CoreEventBus.Publish(@event);
                }
                else
                {
                    Logger.ErrorToTag("UI", string.Format("RenderView pop view失败，未发现场景:{0}", name));
                }
            }));
        }

        #endregion

        /// <summary>
        /// 退出场景
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="frameName"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        //public void OnBack(SwitchMode mode, string frameName, string type, string name)
        //{
        //    this.Dispatcher.Invoke(() =>
        //    {
        //        if (mode == SwitchMode.Pop)
        //        {
        //            for (int index = 0; index < _popViews.Count; index++)
        //            {
        //                PopView view = _popViews[index];
        //                if (view.GetSceneName() == name)
        //                {
        //                    Scene scene = (view.ContentView as RenderView).GetCurrentPart() as Scene;
        //                    if (scene != null)
        //                    {
        //                        Logger.DebugToTag("UI", string.Format("销毁-位置1,PopView，Name:{0}", scene.XFullName));
        //                        scene.Destroy();
        //                    }
        //                    else
        //                    {
        //                        Logger.ErrorToTag("UI", string.Format("存在弹出层，弹出层里没有场景，弹出视图里的contentView：{0}", view.ContentView));
        //                    }
        //                    Logger.DebugToTag("UI", string.Format("ClearAllParts -OnBack, sceneName:{0}", name));
        //                    (view.ContentView as RenderView).ClearAllParts();
        //                    this._ctlLayout.Children.Remove(view);
        //                    this._popViews.RemoveAt(index);

        //                    // 更新视图状态
        //                    this._viewState.CloseScene(name);
        //                    this._viewState.Update();

        //                    //// 发送场景关闭事件
        //                    //Coolzon.Event.Core.CoreCloseSceneCompletedEvent @closeEvent = new Coolzon.Event.Core.CoreCloseSceneCompletedEvent(SwitchMode.Pop,
        //                    //    frameName,
        //                    //    name);
        //                    //Coolzon.Event.Core.CoreEventBus.PublishAsync(@closeEvent);
        //                    break;
        //                }
        //            }

        //            if (_popViews.Count == 0)
        //            {
        //                if (_ctlMainFrame.CurrentPart != null)
        //                {
        //                    // 冻结当前的场景
        //                    _ctlMainFrame.CurrentPart.Unfreeze();

        //                    //// 发送场景打开事件
        //                    //Coolzon.Event.Core.CoreOpenSceneCompletedEvent @event = new Coolzon.Event.Core.CoreOpenSceneCompletedEvent(SwitchMode.Replace, "", _ctlMainFrame.CurrentPart.Name, null);
        //                    //Coolzon.Event.Core.CoreEventBus.Publish(@event);
        //                }
        //            }
        //        }
        //        else
        //        {
        //            if (_ctlMainFrame.CurrentPart != null)
        //                Logger.DebugToTag("UI", string.Format("OnBack-Replace,Name:{0}", _ctlMainFrame.CurrentPart.Name));
        //            else
        //            {
        //                Logger.DebugToTag("UI", "OnBack-Replace");
        //            }
        //            _ctlMainFrame.Back();

        //            //Coolzon.Event.Core.CoreCloseSceneCompletedEvent @closeEvent = new Coolzon.Event.Core.CoreCloseSceneCompletedEvent(SwitchMode.Replace,
        //            //    frameName,
        //            //    name);
        //            //Coolzon.Event.Core.CoreEventBus.PublishAsync(@closeEvent);
        //            // bug
        //            CurrentScene = null;
        //        }
        //    });
        //}

        void popView_Close(View view, bool isCancel)
        {
            this._ctlLayout.Children.Remove(view);
        }

        //public void OnScrollToArea(string frameName, RT.Solution solution, RT.Scene scene, RT.Area area)
        //{
        //    ScrollToArea(scene, area);
        //}

        /// <summary>
        /// 获取当前显示的组件
        /// </summary>
        /// <returns></returns>
        public Scene GetCurrentPart()
        {
            if(_ctlMainFrame.CurrentPart == null)
            {
                Logger.ErrorToTag("RenderView", "CurrentPart为空");
            }
            return _ctlMainFrame.CurrentScene;
        }

        /// <summary>
        /// 预加载part
        /// </summary>
        /// <param name="scenePart"></param>
        public void PreliminaryLoadPart(Scene scenePart)
        {
            //this._ctlMainFrame.PreliminaryLoadPart(scenePart, UIContext.Current.IsShowActiveXPart);
        }

        ///// <summary>
        ///// 滚动场景
        ///// </summary>
        ///// <param name="direction"></param>
        ///// <param name="offset">本次增量</param>
        //public void LoopScene(int direction, double offset)
        //{
        //    if (direction == 0)
        //    {
        //        // left
        //        this._ctlMainFrame.HLoop(offset);
        //    }
        //    else if (direction == 2)
        //    {
        //        // right
        //        this._ctlMainFrame.HLoop(-offset);
        //    }

        //    // 设置视图状态
        //    Scene scenePart = this._ctlMainFrame.CurrentPart as Scene;
        //    this._viewState.SetPartProperty(scenePart.XFullName, Scene.VS_LOOPH, scenePart.DestHLoopOffset.ToString());
        //    this._viewState.Update();
        //}

        public void LoopSceneTo(double destOffset)
        {
            //this._ctlMainFrame.HLoopTo(destOffset);
        }

        //protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
        //{
        //    Swap("S1A1","S1A3");
        //    base.OnPreviewMouseDown(e);
        //}

        /// <summary>
        /// 交换两个区域对象的位置
        /// </summary>
        /// <param name="sourceArea"></param>
        /// <param name="destArea"></param>
        private void Swap(string sourceArea, string destArea)
        {
            if (sourceArea == destArea)
            {
                return;
            }
            //this._ctlMainFrame.SwapArea(sourceArea, destArea);
        }

        ///// <summary>
        ///// 交换区域
        ///// </summary>
        ///// <param name="scene"></param>
        ///// <param name="sourceArea"></param>
        ///// <param name="destArea"></param>
        //[Obsolete("目前启用场景中区域移动的方法，不用交换方法")]
        //public void SwapArea(string scene, string sourceArea, string destArea)
        //{
        //    Common.Logger.DebugToTag("UI", "RenderView OnReceiveSwapAreaCompletedEvent source:{0} dest:{1}",
        //        sourceArea,
        //        destArea);

        //    Swap(sourceArea, destArea);

        //    Common.EventBus.Instance.Publish(new Event.SwapAreaCompletedEvent(scene, sourceArea, destArea));
        //}

        ///// <summary>
        ///// [API]
        ///// 移动区域将sourcearea移动到destArea的前面
        ///// 如果从左往右则移动到destArea的后面
        ///// </summary>
        ///// <param name="scene"></param>
        ///// <param name="sourceArea"></param>
        ///// <param name="destArea"></param>
        //public void MoveArea(string scene, string sourceArea, string destArea)
        //{
        //    if (sourceArea == destArea)
        //    {
        //        return;
        //    }

        //    this.Dispatcher.Invoke(new Action(() =>
        //    {
        //        _ctlMainFrame.MoveArea(sourceArea, destArea);
        //        #region 设置视图状态
        //        Scene scenePart = this._ctlMainFrame.CurrentPart as Scene;
        //        StringBuilder areaposBuilder = new StringBuilder();
        //        for (int index = 0; index < scenePart.ChildrenPosInfo.Count; index++)
        //        {
        //            CPPEI.Coolzon.UI.ChildPos childPos = scenePart.ChildrenPosInfo[index];
        //            areaposBuilder.AppendFormat("{0}:{1},", childPos.Name, childPos.Left);
        //        }
        //        this._viewState.SetPartProperty(scenePart.Name, Scene.VS_AREAPOS, areaposBuilder.ToString());
        //        this._viewState.Update();
        //        #endregion
        //    }));
        //}

        /// <summary>
        /// 切换tab组件的选项卡
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="tabContainer"></param>
        /// <param name="oldTabIndex"></param>
        /// <param name="newTabIndex"></param>
        public void TabChange(string scene, string tabContainer, int oldTabIndex, int newTabIndex)
        {
            Logger.DebugToTag("UI", string.Format("RenderView OnReceiveTabChangeCompetedEvent OldTabIndex:{0} NewTabIndex:{1} Scene:{2} TabContainer:{3}  ",
              oldTabIndex,
              newTabIndex,
              scene,
              tabContainer));
            //this.Dispatcher.Invoke(() =>
            //{
            //    UI.TabContainerPart containerPart = (this._ctlMainFrame.CurrentPart as IPartContainer).GetChildPart(tabContainer, true) as UI.TabContainerPart;
            //    if (containerPart != null)
            //    {
            //        containerPart.SelectTab(newTabIndex);

            //        #region 设置视图状态
            //        this._viewState.SetPartProperty(containerPart.Name, UI.TabContainerPart.VS_TAB, newTabIndex.ToString());
            //        this._viewState.Update();
            //        #endregion

            //        Common.EventBus.Instance.Publish(new Event.TabChangeCompetedEvent(oldTabIndex,
            //            newTabIndex,
            //            scene,
            //            tabContainer));
            //    }
            //    else
            //    {
            //        Common.Logger.ErrorToTag("UI", "未获取到Tab组件：{0}", tabContainer);
            //    }
            //});
        }

        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            Scene scene = this._ctlMainFrame.CurrentPart as Scene;
            if (scene != null)
            {
                Point point = e.GetPosition(scene);
                if (scene.HActualLoopOffset != 0)
                {
                    if (scene.HVirtualLoopOffset < scene.HActualLoopOffset && point.X < scene.HActualLoopOffset)
                    {
                        point.X = scene.HActualLoopOffset + (this.ActualWidth - (scene.HActualLoopOffset - point.X));
                    }
                    else if (scene.HVirtualLoopOffset > scene.HActualLoopOffset && point.X > scene.HVirtualLoopOffset)
                    {
                        point.X = scene.HActualLoopOffset + point.X;
                    }
                }

                //Part part = scene.GetPartAtPoint(typeof(Part), point, scene);
                //if (part != null)
                //{
                //    Logger.DebugToTag("UI", string.Format("Part:{0},MouseLeftButtonDown point:{1},{2}", part.Name, point.X, point.Y));
                //    Service.Contract.ReqMouseEventData requestData = new Service.Contract.ReqMouseEventData();
                //    requestData.SceneName = scene.Name;
                //    requestData.PartName = part.Name;
                //    requestData.EventSource = MouseEventType.MouseLeftDown.Name;
                //    requestData.PointX = point.X;
                //    requestData.PointY = point.Y;
                //    ServiceProxy.ClientProxyManager.Instance.SendRequestSys(
                //        UIContext.Current.ControlDomainId,
                //        UIContext.Current.UserIdentity,
                //        Service.Contract.REQUEST_SCENARIO.SCENE,
                //        Service.Contract.REQUEST_COMMAND.SCENE.MOUSEEVENT,
                //        Service.Contract.REQUEST_MODE.ALL,
                //        requestData);
                //    //part.RaiseMouseEvent(MouseEventType.MouseLeftDown, point);
                //}
            }
            base.OnPreviewMouseLeftButtonDown(e);
        }

        //[Subscribe]
        //public void OnReceiveMouseEventData(Service.Contract.RespMouseEventData responseData)
        //{
        //    this.Dispatcher.Invoke(() =>
        //    {
        //        ScenePart scene = this._ctlMainFrame.CurrentPart as ScenePart;
        //        if (scene != null && scene.Name == responseData.SceneName)
        //        {
        //            UI.Part part = scene.GetChildPart(responseData.PartName, true);
        //            if (part != null)
        //            {
        //                part.RaiseMouseEvent(MouseEventType.Get(responseData.EventSource), new Point(responseData.PointX, responseData.PointY));
        //            }
        //        }
        //    });
        //}

        /// <summary>
        /// 获取现在所显示的区域在场景中的区域信息
        /// </summary>
        /// <returns></returns>
        public Rect GetViewRegionInScene()
        {
            if (this._ctlMainFrame.CurrentPart != null)
            {
                //Point ptRenderView = this._ctlMainFrame.PointToScreen(new Point(0, 0));
                //Point ptScene = this._ctlMainFrame.CurrentPart.PointToScreen(new Point(0, 0));

                //double deltaX = ptRenderView.X - ptScene.X;
                //double deltaY = ptRenderView.Y - ptScene.Y;
                //return new Rect(deltaX, deltaY, this._ctlMainFrame.ActualWidth, this._ctlMainFrame.ActualHeight);
                return new Rect(this._ctlMainFrame.HorizontalOffset,
                    this._ctlMainFrame.VerticalOffset,
                    this._ctlMainFrame.ActualWidth,
                    this._ctlMainFrame.ActualHeight);
            }
            else
            {
                return Rect.Empty;
            }
        }

        void _ctlMainFrame_OnSceneUpdated(Scene scene)
        {
            //Common.EventBus.Instance.Publish(new SceneUpdateEvent(scene, SceneUpdateReason.MoveCamera));
        }

        void _ctlMainFrame_OnSceneOpened(Scene scene)
        {
            //OnUpdateScrollBar(this.RenderSize);
            //Common.EventBus.Instance.Publish(new SceneUpdateEvent(scene, SceneUpdateReason.Open));

            _ctlMask.Visibility = System.Windows.Visibility.Hidden;

            this.ctlPanelDebugToolbar.Children.Clear();
            List<Area> areas = scene.GetRootAreas();
            if(areas.Count > 0)
            {
                ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
                foreach (var area in areas)
                {
                    System.Windows.Controls.Button btn = new System.Windows.Controls.Button();
                    btn.Content = area.Name;
                    btn.Tag = area;
                    btn.Click += btn_Click;
                    this.ctlPanelDebugToolbar.Children.Add(btn);
                }

                //this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                ctlRadioToArea.IsChecked = true;
            }
        }

        protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
        {
            if(e.Delta < 0)
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (areas.Count -1 > _currentLocatedAreaIndex)
                {
                    // next
                    _currentLocatedAreaIndex++;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }
                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (_currentLocatedAreaIndex > 0)
                {
                    // back
                    _currentLocatedAreaIndex--;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }
                if (_currentLocatedAreaIndex > 0)
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
            }
            base.OnPreviewMouseWheel(e);
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);
        }

        protected override void OnPreviewKeyUp(KeyEventArgs e)
        {
            if (e.Key == Key.Right)
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    // next
                    _currentLocatedAreaIndex++;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }
                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
            }
            else if(e.Key == Key.Left)
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (_currentLocatedAreaIndex > 0)
                {
                    // back
                    _currentLocatedAreaIndex--;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }
                if (_currentLocatedAreaIndex > 0)
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
            }
            base.OnPreviewKeyUp(e);
        }

        private void ctlBtnBack_Click(object sender, RoutedEventArgs e)
        {
            if (sender == ctlBtnNext)
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    // next
                    _currentLocatedAreaIndex++;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }

                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                if (_currentLocatedAreaIndex > 0)
                {
                    // back
                    _currentLocatedAreaIndex--;
                    this.Frame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                    ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;
                }
                if (_currentLocatedAreaIndex > 0)
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                }
                ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
            }
        }

        void btn_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Controls.Button btn = sender as System.Windows.Controls.Button;
            this.Frame.Locator.Locate((Area)btn.Tag);
            ctlLabelCaption.Text = ((Area)btn.Tag).AreaMatadata.Caption;
        }

        /// <summary>
        /// 执行脚本
        /// </summary>
        /// <param name="scriptCode"></param>
        public void ExecuteJs(string scriptCode)
        {
            //_ctlMainFrame.ExecuteJs(scriptCode);
        }

        public void ValidateCurrentPartVisibleRange()
        {
            if (_popViews != null && _popViews.Count > 0)
            {
                (_popViews[_popViews.Count - 1].ContentView as RenderView).ValidateCurrentPartVisibleRange();
            }
            else
            {
                _ctlMainFrame.ValidateCurrentPartVisibleRange();
            }
        }

        /// <summary>
        /// 清楚渲染视图里所有的组件引用关系
        /// </summary>
        public void ClearAllParts()
        {
            if (_popViews != null && _popViews.Count > 0)
            {
                for (int index = 0; index < _popViews.Count; index++)
                {
                    (_popViews[index].ContentView as RenderView).ClearAllParts();
                }
            }

            // 保存状态的age不变
            long storeViewStateAge = _viewState.Age;
            _viewState = ViewState.FromToken(string.Empty);
            _viewState.UpdateAge(storeViewStateAge++);

            //_ctlMainFrame.ClearAllParts();

            this.Solution = null;
            this.CurrentScene = null;
        }

        public PartContext GetPartContext()
        {
            return _ctlMainFrame.PartContext;
        }

        #region magnify
        private VisualBrush _magnifierVisualBrush;
        private Storyboard _moveMagnifyStoryboard;
        private DoubleAnimation _moveMagnifyAnimationTop;
        private DoubleAnimation _moveMagnifyAnimationLeft;
        public void ShowMagnify(Point pos, double rate, double radius, double duration)
        {
            this.Dispatcher.Invoke(() =>
            {
                double sourceW = 800 / 2.0d;
                double sourceH = 800 / 2.0d;
                double halfW = 800 / 2.0d;
                double halfH = 800 / 2.0d;
                double left = pos.X - halfW;
                double top = pos.Y - halfH;

                double currentLeft = 0;
                double currentTop = 0;
                if (_magnifierVisualBrush == null)
                {
                    currentLeft = 0;
                    currentTop = 0;

                    _magnifierVisualBrush = new VisualBrush(this.GetCurrentPart());
                    _magnifierVisualBrush.ViewboxUnits = BrushMappingMode.Absolute;
                    _magnifierVisualBrush.Viewbox = new Rect(pos.X - sourceW / 2, pos.Y - sourceH / 2, sourceW, sourceH);
                    _ctlMagnifier.Fill = _magnifierVisualBrush;
                }
                else
                {
                    currentLeft = System.Windows.Controls.Canvas.GetLeft(this._ctlMagnifier);
                    currentTop = System.Windows.Controls.Canvas.GetTop(this._ctlMagnifier);
                    //_magnifierVisualBrush.Viewbox = new Rect(pos.X - sourceW / 2, pos.Y - sourceH / 2, sourceW, sourceH);
                }

                if (_moveMagnifyStoryboard == null)
                {
                    _moveMagnifyStoryboard = new Storyboard();
                    //_moveMagnifyStoryboard.FillBehavior = FillBehavior.HoldEnd;
                    _moveMagnifyAnimationTop = new DoubleAnimation(currentTop, top, new Duration(TimeSpan.FromSeconds(duration)));
                    Storyboard.SetTarget(_moveMagnifyAnimationTop, this);
                    Storyboard.SetTargetProperty(_moveMagnifyAnimationTop, new PropertyPath(RenderView.XMagnifyTopProperty));

                    _moveMagnifyAnimationLeft = new DoubleAnimation(currentLeft, left, new Duration(TimeSpan.FromSeconds(duration)));
                    Storyboard.SetTarget(_moveMagnifyAnimationLeft, this);
                    Storyboard.SetTargetProperty(_moveMagnifyAnimationLeft, new PropertyPath(RenderView.XMagnifyLeftProperty));

                    _moveMagnifyStoryboard.Children.Add(_moveMagnifyAnimationTop);
                    _moveMagnifyStoryboard.Children.Add(_moveMagnifyAnimationLeft);
                    _moveMagnifyStoryboard.Begin(_ctlMagnifier);
                }
                else
                {
                    _moveMagnifyAnimationTop.From = currentTop;
                    _moveMagnifyAnimationTop.To = top;

                    _moveMagnifyAnimationLeft.From = currentLeft;
                    _moveMagnifyAnimationLeft.To = left;
                    //_moveMagnifyStoryboard.Remove(this);
                    _moveMagnifyStoryboard.Begin(_ctlMagnifier);
                }

                this._ctlMagnifier.Visibility = Visibility.Visible;
            });
        }

        public void HideMagnify()
        {
            this.Dispatcher.Invoke(() =>
            {
                //_ctlMainFrame.HideMagnify();

                _ctlMagnifier.Fill = null;
                _magnifierVisualBrush = null;
                this._ctlMagnifier.Visibility = Visibility.Hidden;
            });
        }
        #endregion

        #region laser pointer
        public void ShowLaserPointer(Point pos, double radius, double duration, int color)
        {
            //this.Dispatcher.Invoke(() =>
            //{
            //    _ctlMainFrame.ShowLaserPointer(pos, radius, duration, color);
            //});
        }

        public void HideLaserPointer()
        {
            //this.Dispatcher.Invoke(new Action(() =>
            //{
            //    _ctlMainFrame.HideLaserPointer();
            //}));
        }
        #endregion

        /// <summary>
        /// 重置方案
        /// </summary>
        public void ResetSolution()
        {
            _viewState.UpdateAndResetPartState();
            // 重置当前方案
            // 默认显示到第一个场景上
            OpenSceneArgs openSceneArgs = new OpenSceneArgs();
            openSceneArgs.ParametersString.Add("sys:isresetviewstate", "true");
            OpenScene(SwitchMode.Replace, "", "", Solution.Scenes.First().Name, openSceneArgs);
        }

        ///// <summary>
        ///// 重置场景
        ///// </summary>
        ///// <param name="scene"></param>
        //public void ResetScene(Scene scene)
        //{
        //    Scene currentScene = _ctlMainFrame.CurrentPart as Scene;
        //    if (currentScene != null)
        //    {
        //        // 重置场景里的显示效果
        //        currentScene.Reset();
        //        currentScene.ResetViewState(_viewState);
        //        _viewState.Update();
        //    }
        //}

        #region viewstate

        ///// <summary>
        ///// 更新组件的视图状态
        ///// 当组件的收到事件后更新了自己的显示，需要保存视图状态
        ///// </summary>
        ///// <param name="part"></param>
        //public void UpdatePartViewState(Part part)
        //{
        //    this.Dispatcher.Invoke(() =>
        //    {
        //        part.SaveViewState(_viewState);
        //    });
        //    _viewState.Update();
        //}

        /// <summary>
        /// 重置视图状态，但是不更新组件的渲染效果
        /// </summary>
        public void ResetViewStateNotUpdatePart()
        {
            long storeViewStateAge = _viewState.Age;
            _viewState = ViewState.FromToken(string.Empty);
            _viewState.UpdateAge(storeViewStateAge++);
        }

        public void SetViewState(ViewState viewState)
        {
            //this.Dispatcher.Invoke(new Action(() =>
            //{
            //    _viewState = viewState;
            //    _ctlMainFrame.SetViewState(viewState);
            //}));
        }

        public string GetViewStateToken()
        {
            return ViewState.ToToken(this._viewState);
        }

        public ViewState GetViewState()
        {
            return this._viewState;
        }
        #endregion

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            OnUpdateScrollBar(sizeInfo.NewSize);
            base.OnRenderSizeChanged(sizeInfo);
        }

        private void OnRadioStretchModeChecked(object sender, RoutedEventArgs e)
        {
            if (sender == ctlRadioFill)
            {
                this._ctlMainFrame.Locator.Stretch = Stretch.Fill;
            }
            else if (sender == ctlRadioUniform)
            {
                this._ctlMainFrame.Locator.Stretch = Stretch.Uniform;
            }
            else if (sender == ctlRadioUniformToFill)
            {
                this._ctlMainFrame.Locator.Stretch = Stretch.UniformToFill;
            }
            else
            {
                this._ctlMainFrame.Locator.Stretch = Stretch.None;
            }
        }

        private void ctlRadioToScene_Checked(object sender, RoutedEventArgs e)
        {
            if (sender == ctlRadioToScene)
            {
                _ctlMainFrame.Locator.Locate(_ctlMainFrame.CurrentScene);
                ctlLabelCaption.Text = _ctlMainFrame.CurrentScene.SceneMatadata.Caption;
                ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                ctlBtnNext.Visibility = System.Windows.Visibility.Hidden;
            }
            else
            {
                //_currentLocatedAreaIndex = 0;
                List<Area> areas = this.Frame.CurrentScene.GetRootAreas();
                this._ctlMainFrame.Locator.Locate(areas[_currentLocatedAreaIndex]);
                ctlLabelCaption.Text = areas[_currentLocatedAreaIndex].AreaMatadata.Caption;

                if (_currentLocatedAreaIndex > 0)
                {
                    // back
                    ctlBtnBack.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnBack.Visibility = System.Windows.Visibility.Hidden;
                }


                if (areas.Count - 1 > _currentLocatedAreaIndex)
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    ctlBtnNext.Visibility = System.Windows.Visibility.Hidden;
                }
            }
        }

        private void ctlBtnExit_Click(object sender, RoutedEventArgs e)
        {
            App.Current.MainWindow.Close();
        }
    }
}
